#ifndef CUBE_MATH_H
#define CUBE_MATH_H
#include <cubEPrimitive.hh>

namespace CubE
{
   //global variables and functions
   
   const float PI =  3.1415926f;

   bool IsFloatEqual(float a, float b);

   class Radian;
   
   class Degree
   {
     public:
      Degree(void);
      Degree(Radian rad);
      Degree(float val);

      float Value(void) const { return _value; }

     private:
      float _value;
   };

   class Radian
   {
     public:
      Radian(void);
      Radian(Degree deg);
      Radian(float val);

      float Value(void) const { return _value;  }
      
     private:
      float _value;
   };

   class Quaternion
   {
     public:
      Quaternion(void);
      Quaternion(Quaternion const& other);
      Quaternion(Vector3 axis, Degree angle);
      Quaternion(Vector3 axis, Radian angle);
      Quaternion(Vector3 iVec, float rW);
      Quaternion(const Vector3& from, const Vector3& dest);

      Vector3 GetImaginaryPart(void) const
      { return _iVec; }

      float GetRealPart(void) const
      {return _rW; }

      Quaternion GetConjugate(void) const;

      Quaternion operator*(const Quaternion& other) const;

      void Normalize(void);
      bool IsNormalized(void);
      float GetLength(void);

     private:
      void initialize(float x, float y, float z, float w);
      void initialize(Vector3 imaginary_part, float real_part);
      
     private:
      /* q = [ _iVec, _rW ]
       *_iVec(x,y,z) belongs to Imaginary part,
       * and _rW belongs to Real part
       */
      Vector3 _iVec;
      float  _rW;
   };
   
}

#endif
